import { cloneDeep } from 'lodash-es'

// 生成随机字符串
export const randomStr = (len = 9) => {
    const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
    const str = [...Array(len).keys()].map(() => chars.charAt(Math.floor(Math.random() * chars.length))).join('')
    return `wl${str}`
}

// 深度克隆
export const deepClone = data => {
    return cloneDeep(data)
}

export const isNumberStr = str => /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)

export const test = {
    // 验证电子邮箱格式
    email: value => /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value),
    // 验证手机格式
    mobile: value => /^1[23456789]\d{9}$/.test(value),
    // 验证十进制数字
    number: value => /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value),
    // 验证整数
    digits: value => /^\d+$/.test(value),
    // 验证URL格式
    url: value => /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?/.test(value),
    // 验证日期格式
    date: value => !/Invalid|NaN/.test(new Date(value).toString()),
    // 验证ISO类型的日期格式
    dateISO: value => /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value),
    // 验证ISO8601类型的日期格式
    dateISO8601: value => {
        if (!/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(value)) return false
        return new Date(value).toISOString() === value
    },
    // 验证身份证号码
    idCard: value => /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value),
    // 中文
    chinese: value => /^[\u4e00-\u9fa5]+$/gi.test(value),
    // 只能输入字母
    letter: value => /^[a-zA-Z]*$/.test(value),
    // 只能是字母或者数字
    enOrNum: value => /^[0-9a-zA-Z]*$/g.test(value)
}

// 从 html 富文本中提取纯文本
export const getHtmlText = html => (html?.replace(/<.+?>/g, '') || html)

/**
 * @description 绑定事件 on(element, event, handler)
 */
export const on = (function () {
    if (document.addEventListener) {
        return function (element, event, handler, useCapture = false) {
            if (element && event && handler) {
                element.addEventListener(event, handler, useCapture)
            }
        }
    } else {
        return function (element, event, handler, useCapture = false) {
            if (element && event && handler) {
                element.attachEvent('on' + event, handler)
            }
        }
    }
})()

/**
 * @description 解绑事件 off(element, event, handler)
 */
export const off = (function () {
    if (document.removeEventListener) {
        return function (element, event, handler, useCapture = false) {
            if (element && event) {
                element.removeEventListener(event, handler, useCapture)
            }
        }
    } else {
        return function (element, event, handler, useCapture = false) {
            if (element && event) {
                element.detachEvent('on' + event, handler)
            }
        }
    }
})()

/**
 * @description 时间格式化 timeFormat(dateTime, fmt)
 */
// 其他更多是格式化有如下:
// yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合
export const timeFormat = (dateTime = null, fmt = 'yyyy-mm-dd') => {
	// 如果为null,则格式化当前时间
	if (!dateTime) dateTime = Number(new Date())
	// 如果dateTime长度为10或者13，则为秒和毫秒的时间戳，如果超过13位，则为其他的时间格式
	if ((dateTime.toString().length == 10) && test.number(dateTime)) dateTime *= 1000
    // 检查是否是ISO8601格式
    if (test.dateISO8601(dateTime)) {
        const newDate = new Date(dateTime).toJSON()
        dateTime = new Date(+new Date(newDate) + 8 * 3600 * 1000).toISOString().replace(/T/g, ' ').replace(/\.[\d]{3}Z/, '')
    }
	let date = new Date(dateTime)
	let ret
	let opt = {
		"y+": date.getFullYear().toString(), // 年
		"m+": (date.getMonth() + 1).toString(), // 月
		"d+": date.getDate().toString(), // 日
		"h+": date.getHours().toString(), // 时
		"M+": date.getMinutes().toString(), // 分
		"s+": date.getSeconds().toString() // 秒
		// 有其他格式化字符需求可以继续添加，必须转化成字符串
	};
	for (let k in opt) {
		ret = new RegExp('(' + k + ')').exec(fmt)
		if (ret) {
			fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, '0')))
		}
	}
	return fmt;
}

// 是否是连续数字组
export const isContinuationNum = nums => {
    const list = [...nums]
    list.sort((a, b) => a - b)
    for (let i = 1; i < list.length; i++) {
        if (list[i] - list[i - 1] !== 1) {
            return false
        }
    }
    return true
}

// 驼峰转换横线
export const humpToLine = str => str.replace(/([A-Z])/g, '-$1').toLowerCase()

// 横线转换驼峰
export const lineToHump = str => str.replace(/\-(\w)/g, (all, letter) => letter.toUpperCase())